#!/usr/bin/perl -w

#
#NOTES: 
#
# use \savebox to make numbers align??
# use fractions for all computations
# add Nine Chapters problems w/ drop down menu

#
#PERL MODULES
#

use strict;
use CGI qw/:standard/;
#use CGI qw/-no_undef_params -nosticky :all/;
use CGI::Carp qw(fatalsToBrowser);

#
#VARIABLES
#

my $query = new CGI; 
my $formattedtabledata;
my %a;
my %b;
my %c;
my %num;
my %denom;
my %sign;
my @JZSS = "";
my @JZSSproblems = "";
my $N = "";
my $M = "";
my $matrix = "";
my $cmatrix = "";
my @matrices = "";
my @cmatrices = "";
my @abstractmatrices = "";
my @result = "";
my $denominator;
my @cresult = "";
my $cintegers = 1;
my $error = "";
my $pm = "";
my $pm1 = 1;
my $noninteger = 0;
my $usegcf =0;
my $JZSSnum = "";
my $reducetens = 1;
my @formula = "";
my @boardnotes = "";
my @calcnotes = "";
my @formulanotes = "";
my $output;
my $table_a = ""; 
my $table_header = ""; 
my $print_a = "";
my @frac;
my $inputerror = "";


#
#MATRICES
#

#JZSS
#3
$JZSS[1] = [["2", "1", "0", "1"], ["0", "3", "1", "1"], ["1", "0", "4", "1"]];
#12
$JZSS[2] = [["1", "1", "0", "40"], ["0", "2", "1", "40"], ["1", "0", "3", "40"]];
#13
$JZSS[3] = [["2", "1", "0", "0", "0", "721"], ["0", "3", "1", "0", "0", "721"], ["0", "0", "4", "1", "0", "721"], ["0", "0", "0", "5", "1", "721"], ["1", "0", "0", "0", "6", "721"]];
#15
$JZSS[4] = [["2", "-1", "0", "1"], ["0", "3", "-1", "1"], ["-1", "0", "4", "1"]];

# YHJZSS
$JZSS[5] = [["2", "1", "0", "2500"], ["0", "3", "1", "2500"], ["1", "0", "4", "2500"]];

#SXZJ
$JZSS[6] = [["15", "1670", "0", "0", "106000"], ["0", "800", "264", "0", "106000"], ["0", "0", "40", "200", "106000"], ["52", "0", "0", "175/3", "106000"]];

#744.4
$JZSS[7] = [["2", "1", "0", "1"], ["0", "3", "1", "1"], ["1", "0", "4", "2"]];

#747.3
$JZSS[8] = [["4", "-1", "0", "300"], ["0", "5", "-1", "300"], ["-1", "0", "6", "300"]];

#750.2
$JZSS[9] = [["2", "4", "0", "0", "40"], ["0", "2", "7", "0", "40"], ["0", "0", "4", "7", "30"], ["1", "0", "0", "8", "24"]];

#SFTZ
#4**
$JZSS[10] = [["1", "1", "0", "42"], ["0", "2", "1", "42"], ["1", "0", "3", "42"]];
#5**
$JZSS[11] = [["2", "3", "0", "2040"], ["0", "5", "6", "640"], ["3", "0", "7", "2980"]];
#8**
$JZSS[12] = [["2", "4", "0", "0", "40"], ["0", "2", "7", "0", "40"], ["0", "0", "4", "7", "30"], ["1", "0", "0", "8", "24"]];

#359.3
$JZSS[13] = [["10", "1", "0", "0", "1"], ["0", "10", "2", "0", "1"], ["0", "0", "10", "3", "1"], ["4", "0", "0", "10", "1"]];

#366.4
$JZSS[14] = [["1", "1", "0", "42"], ["0", "2", "1", "42"], ["1", "0", "3", "42"]];

#372.3
$JZSS[15] = [["2", "4", "0", "0", "40"], ["0", "2", "7", "0", "40"], ["0", "0", "4", "7", "30"], ["1", "0", "0", "8", "24"]];

#373.3
$JZSS[16] = [["1", "8", "0", "0", "24"], ["0", "7", "4", "0", "30"], ["0", "0", "7", "2", "40"], ["2", "0", "0", "4", "40"]];

#374.1
$JZSS[17] = [["2", "7", "0", "0", "40"], ["0", "4", "7", "0", "30"], ["0", "0", "8", "1", "24"], ["4", "0", "0", "2", "40"]];

$JZSS[18] = [["1", "1/3", "0", "0", "0", "1442"], ["0", "1", "1/4", "0", "0", "1442"], ["0", "0", "1", "1/5", "0", "1442"], ["0", "0", "0", "1", "1/6", "1442"], ["1/2", "0", "0", "0", "1", "1442"]];

$JZSS[19] = [["1", "-1/3", "0", "0", "0", "719"], ["0", "1", "-1/4", "0", "0", "719"], ["0", "0", "1", "-1/5", "0", "719"], ["0", "0", "0", "1", "-1/6", "719"], ["-1/2", "0", "0", "0", "1", "719"]];

$JZSS[20] = [["1", "-1/3", "0", "0", "0", "0"], ["0", "1", "-1/4", "0", "0", "0"], ["0", "0", "1", "-1/5", "0", "0"], ["0", "0", "0", "1", "-1/6", "0"], ["1/2", "0", "0", "0", "1", "721"]];

$JZSS[21] = [["10", "1", "0", "0", "9976"], ["0", "10", "2", "0", "9976"], ["0", "0", "10", "3", "9976"], ["4", "0", "0", "10", "9976"]];

$JZSS[22] = [["2/5", "1", "0", "6780"], ["0", "2/3", "1", "6780"], ["1", "0", "2/7", "6780"]];

$JZSS[23] = [["3", "30", "0", "0", "0", "0", "0", "0", "0", "45"], ["0", "30", "-120", "0", "0", "0", "0", "0", "0", "0"], ["0", "0", "100", "-50", "0", "0", "0", "0", "0", "0"], ["0", "0", "0", "30", "30", "0", "0", "0", "0", "18"], ["0", "0", "0", "0", "50", "10", "0", "0", "0", "45"], ["0", "0", "0", "0", "0", "15", "17", "0", "0", "111/2"], ["0", "0", "0", "0", "0", "0", "20", "-40", "0", "28"], ["0", "0", "0", "0", "0", "0", "0", "20", "-10", "0"], ["2", "0", "0", "0", "0", "0", "0", "0", "80", "34"]];

@JZSSproblems = (1..23);

#
#  SUBROUTINES
#

#LOAD MATRIX SUBROUTINES

sub nofractions {
    foreach my $n (1..$N){
	foreach my $m (1..$M){
	    if ($a{$n}{$m} =~m/(\d+)\/(\d+)/){
		my $num = $1;
		my $denom = $2;
		my $gcf = &gcf($num,$denom);
		$num /= $gcf;
		$denom /= $gcf;
		foreach my $p (1..$M) {
		    $a{$n}{$p} *= $denom;
		}
	    }
	}
    }
}

sub JZSS {
    my ($t) = @_;
    $N = $#{$JZSS[$t][0]}; 
    $M = $N + 1;
    my $i = 1;
    my $j =1;
    foreach my $n (1..$N) {
	foreach my $m (1..$M) {
	    $b{$n}{$m} = $JZSS[$t][$n-1][$m-1];
	    if ($JZSS[$t][$n-1][$m-1] =~s/^-//){ 
		$sign{$n}{$m} = -1;  
	    }else{
		$sign{$n}{$m} = 1;  
	    }
	    if (($JZSS[$t][$n-1][$m-1] == "") or ($JZSS[$t][$n-1][$m-1] =~ m/^0+$/)) { #blank or all zeros, possibly -
		$num{$n}{$m} = 0;
		$denom{$n}{$m} = 1;
		$sign{$n}{$m} = 1;
	    }elsif ($JZSS[$t][$n-1][$m-1] =~ m/^(\d+)$/) {
		$num{$n}{$m} = $1;
		$denom{$n}{$m} = 1;
	    }elsif ($JZSS[$t][$n-1][$m-1] =~m/^(\d+)\/(\d+)$/){
		$num{$n}{$m} =$1;
		$denom{$n}{$m} =$2;
		if ($denom{$n}{$m} == 0) {
		    $denom{$n}{$m} = 1;
		}
		my $gcf = &gcf($num{$n}{$m},$denom{$n}{$m});
		$num{$n}{$m} /=$gcf || print "Divided by 0\n";
		$denom{$n}{$m} /=$gcf || print "Divided by 0\n";
	    }else{
		print "Error! \"$JZSS[$t][$n-1][$m-1]\" \n";
	    }
	}
	my $lcm = 1;
	my $gcf = &gcf($denom{$n}{1},$denom{$n}{2});
	foreach my $m (3..$M) {
	    $gcf = &gcf($gcf,$denom{$n}{$m});
	}
	foreach my $m (1..$M) {
	    $lcm *= $denom{$n}{$m};
	    $lcm /= $gcf;
	}
	foreach my $m (1..$M) {
	    unless ($denom{$n}{$m} == 0 ){
		$a{$n}{$m} = ($sign{$n}{$m} * $num{$n}{$m} * $lcm) / $denom{$n}{$m};
	    }
	}
    }
    return %a;
}

sub random_a {
    foreach my $n (1..$N) {
	foreach my $m (1..$N) {
	    $a{$n}{$m} =  int(rand(8))+1;
	}
	$a{$n}{$N+1} =  int(rand(149))+1;
    }
}

# MATRIX CALCULATION SUBROUTINES

sub noninteger {
    $noninteger = 0;
    foreach my $n (1..$N) {
	foreach my $m (1..$M) {
	    if ($a{$n}{$m} != int($a{$n}{$m})) {$noninteger = 1};
	}
    }
    return $noninteger;
}

sub pm {
    my ($n) = @_;
    if ($n % 2 == 0) {$pm = "+"} else {$pm = "-"};
    return $pm;
}

sub pm1 {
    my ($n) = @_;
    if ($n % 2 == 0) {$pm1 = 1} else {$pm1 = -1};
    return $pm1;
}


sub determinants {
    &nofractions;
    $matrices[0] = &print_matrix;
    &num2rods;
    $cmatrices[0] = &print_cmatrix;
    &print_abstractmatrix(0);
    $boardnotes[0] .= qq{<p>Arranged on the counting board, we have:</p>};
    $calcnotes[0] .= qq{<p>This corresponds to the following augmented matrix:</p>};
    $formulanotes[0] .= qq{<p>Using variables, we can show what this corresponds to in terms of an exemplar:</p>};
    my $anN = $a{$N}{1};
    foreach my $n (2..$N-1) {
	$anN *= $a{$n-1}{$n};
	$a{$N}{$n} = &pm1($n-1) * $anN;
	$matrices[$n-1] = &print_matrix;
	&num2rods;
	$cmatrices[$n-1] = &print_cmatrix;
	&print_abstractmatrix($n-1);
    };
    $formula[$N] = qq{ k_1 b_{$N} - l_{$N}b_1 };
    $result[1] = $a{1}{1} * $a{$N}{$M} - $a{$N}{1} * $a{1}{$M} ;
    $cresult[1] = &onenum2rods($result[1]);
    foreach my $n (2..$N-1) {
	#calculate result
	$result[$n] = $result[$n-1];
	$result[$n] *= $a{$n}{$n};
	$result[$n] -= $a{$N}{$n} * $a{$n}{$M} ;
	#convert to cresult
	$cresult[$n] = &onenum2rods($result[$n]);
	#create formula
	$formula[$N+$n-1] = "(" . $formula[$N-2+$n];
	my $r = $N-$n+1; 
	&pm($n);
	$formula[$N+$n-1] .= qq{ ) k_{$n}  $pm };
    my $s = $n -1;
    $formula[$N+$n-1] .= qq{ l_{$N} };
    foreach my $i (1..$n -1) {
	if ($i < $n -1 ) {
	    $formula[$N+$n-1] .= qq{ l_{$i}  };
	}
    }
    $formula[$N+$n-1] .= qq{ l_{$s} b_{$n} };
};
#calculate result
$denominator = 1;
foreach my $n (1..$N) {
    $denominator *= $a{$n}{$n};
}
my $subtractand = -$a{$N}{1};
foreach my $n (1..$N-1) {
    $subtractand *= -$a{$n}{$n+1};
}
$denominator -= $subtractand;
&frac(1,0,$result[$N-1],$denominator);
$result[$N] = "x_{$N} = ";
if ($frac[2] == 0) {
    $result[$N] .= $frac[0] * $frac[1];
}else{
    if ($frac[0] == 1) {
	$result[$N] .= "\\frac{$frac[2]}{$frac[3]}"
	}else{
	    $result[$N] .= "-\\frac{$frac[2]}{$frac[3]}"
	    }
    #$result[$N] = " \\text{ or } $mixedfrac[0]\\frac{$mixedfrac[1]}{$mixedfrac[2]}"
}
#convert to cresult
#$cresult[$n] = &onenum2rods($result[$n]);
#create formula
my $denom = "";
foreach my $n (1..$N) {
    $denom .= "k_{$n}";
}
$denom .= "$pm";
foreach my $n (1..$N) {
    $denom .= "l_{$n}";
}

$formula[2*$N]= "x_{$N} = \\frac{" . $formula[2*$N-2] . "}{$denom}}";
};

sub gcf {
    my ($x, $y) = @_;
    ($x, $y) = ($y, $x % $y) while $y;
    return $x;
}

sub reducetens {
    my ($n) = @_;
    if ($reducetens) {
	my $alltens = 1;
	while ($alltens) {
	    foreach my $m (0..$M) {
		if (int($a{$n}{$m}/10) != ($a{$n}{$m}/10)) {
		    $alltens = 0;
		};
	    }
	    if ($alltens) {
		foreach my $m (1..$M) {
		    $a{$n}{$m} = $a{$n}{$m} /10;
		}
	    }
	}
    }
}


sub rowReduction {
    foreach my $i (1..($N-1)) {
	if ($a{$i}{$i} != 0) { #need else: use another pivot
	    foreach my $n (($i+1)..$N) {
		if ($a{$n}{$i} != 0){
		    if ($a{$i}{$i} == $a{$n}{$i} ){
			foreach my $m ($i..$M) {
			    $a{$n}{$m} = ($a{$n}{$m} - $a{$i}{$m});
			}
			&reducetens($n);
		    } else {
			my $gcf = 1; 
			if ($usegcf) { $gcf = &gcf($a{$i}{$i},$a{$n}{$i}) };
			my $nmult = $a{$i}{$i}/$gcf;
			my $imult = $a{$n}{$i}/$gcf;
			foreach my $m (1..$M) {
			    $a{$n}{$m} = $nmult*$a{$n}{$m} - $imult*$a{$i}{$m};
			}
			&reducetens($n);
		    }
		}
	    }
	}
	$matrices[$i] = &print_matrix;
	&noninteger;
	&num2rods;
	$cmatrices[$i] = &print_cmatrix;
    }
}

sub backSubstitution {
    foreach my $i ( reverse (1..($N-1))) {
	my $bi = 0;
	$bi += $a{$N}{$N}*$a{$i}{$M};
	foreach my $j ( reverse (($i+1)..$N)) {
	    $bi -= $a{$j}{$M}*$a{$i}{$j};
	}
	if ($a{$i}{$i} == 0 ) {
	    $error .= "ann = $a{$i}{$i} for n = $i<p>";
	}else{
	    $bi /= $a{$i}{$i};
	    if (int($bi)!=$bi ) {
		$error .= "bi = $bi for n = $i<p>";
	    }
	    $a{$i}{$M} = $bi;
	    foreach my $k (reverse ($i..$N)) {
		$a{$i}{$k}=0;
	    }
	}
	&noninteger;
	$matrices[2*$N-$i] = &print_matrix;
	&num2rods;
	$cmatrices[2*$N-$i] = &print_cmatrix;
    }
}

#Fraction subroutines

sub add {}

sub subtract {}

sub multiply {}

sub divide {}

sub reduce {}

sub frac {
    my ($sign,$int,$num,$denom) = @_;
    #put sign in $sign
    if ($int != abs($int)) {$int *= -1; $sign *= -1};
    if ($num != abs($num)) {$num *= -1; $sign *= -1};
    if ($denom != abs($denom)) {$denom *= -1; $sign *= -1};
    #calculate if fraction
    if ($num != 0){ 
	$num += $int*$denom;
	$int = 0;
	unless ($denom == 0) { #make sure not dividing by 0
	    $int = int($num/$denom);
	    if ( $num/$denom == $int ) { #if result is integer
		$num = 0;
		$denom = 1;
	    }else{ 
		my $gcf = &gcf($num, $denom);
		$num /= $gcf;
		$denom /= $gcf;
	    }
	}
    }
    @frac = ($sign, $int, $num, $denom);
    return @frac;
}


#PRINT MATRIX SUBROUTINES

sub num2rods {
    unless ($noninteger) {
	foreach my $n (1..$N) {
	    foreach my $m (1..$M) {
		my $number = "";
		$c{$n}{$m} = "";
		if ($a{$n}{$m} >= 0 ) {
		    $number = $a{$n}{$m};
		    while ( $number ne "" ) { 
			my $digit = "";
			$number =~s/\d$//;
			$digit = $&;
			$c{$n}{$m} = "~" . $c{$n}{$m};
			$c{$n}{$m} = "\\zero" . $c{$n}{$m} if $digit == 0;
			$c{$n}{$m} = "\\one" . $c{$n}{$m} if $digit == 1;
			$c{$n}{$m} = "\\two" . $c{$n}{$m} if $digit == 2;
			$c{$n}{$m} = "\\three" . $c{$n}{$m} if $digit == 3;
			$c{$n}{$m} = "\\four" . $c{$n}{$m} if $digit == 4;
			$c{$n}{$m} = "\\five" . $c{$n}{$m} if $digit == 5;
			$c{$n}{$m} = "\\six" . $c{$n}{$m} if $digit == 6;
			$c{$n}{$m} = "\\seven" . $c{$n}{$m} if $digit == 7;
			$c{$n}{$m} = "\\eight" . $c{$n}{$m} if $digit == 8;
			$c{$n}{$m} = "\\nine" . $c{$n}{$m} if $digit == 9;
			if ($number ne "") {
			    my $ten = "";
			    $number =~s/\d$//;
			    $ten = $&;
			    $c{$n}{$m} = "~" . $c{$n}{$m};
			    $c{$n}{$m} = "\\zero" . $c{$n}{$m} if $ten == 0;
			    $c{$n}{$m} = "\\ten" . $c{$n}{$m} if $ten == 1;
			    $c{$n}{$m} = "\\twenty" . $c{$n}{$m} if $ten == 2;
			    $c{$n}{$m} = "\\thirty" . $c{$n}{$m} if $ten == 3;
			    $c{$n}{$m} = "\\forty" . $c{$n}{$m} if $ten == 4;
			    $c{$n}{$m} = "\\fifty" . $c{$n}{$m} if $ten == 5;
			    $c{$n}{$m} = "\\sixty" . $c{$n}{$m} if $ten == 6;
			    $c{$n}{$m} = "\\seventy" . $c{$n}{$m} if $ten == 7;
			    $c{$n}{$m} = "\\eighty" . $c{$n}{$m} if $ten == 8;
			    $c{$n}{$m} = "\\ninety" . $c{$n}{$m} if $ten == 9;
			}
		    }
		}else{
		    $number = -$a{$n}{$m};
		    while ( $number ne "" ) { 
			my $digit = "";
			$number =~s/\d$//;
			$digit = $&;
			$c{$n}{$m} = "~" . $c{$n}{$m};
			$c{$n}{$m} = "\\Zero" . $c{$n}{$m} if $digit == 0;
			$c{$n}{$m} = "\\One" . $c{$n}{$m} if $digit == 1;
			$c{$n}{$m} = "\\Two" . $c{$n}{$m} if $digit == 2;
			$c{$n}{$m} = "\\Three" . $c{$n}{$m} if $digit == 3;
			$c{$n}{$m} = "\\Four" . $c{$n}{$m} if $digit == 4;
			$c{$n}{$m} = "\\Five" . $c{$n}{$m} if $digit == 5;
			$c{$n}{$m} = "\\Six" . $c{$n}{$m} if $digit == 6;
			$c{$n}{$m} = "\\Seven" . $c{$n}{$m} if $digit == 7;
			$c{$n}{$m} = "\\Eight" . $c{$n}{$m} if $digit == 8;
			$c{$n}{$m} = "\\Nine" . $c{$n}{$m} if $digit == 9;
			if ($number ne "") {
			    my $ten = "";
			    $number =~s/\d$//;
			    $ten = $&;
			    $c{$n}{$m} = "~" . $c{$n}{$m};
			    $c{$n}{$m} = "\\Zero" . $c{$n}{$m} if $ten == 0;
			    $c{$n}{$m} = "\\Ten" . $c{$n}{$m} if $ten == 1;
			    $c{$n}{$m} = "\\Twenty" . $c{$n}{$m} if $ten == 2;
			    $c{$n}{$m} = "\\Thirty" . $c{$n}{$m} if $ten == 3;
			    $c{$n}{$m} = "\\Forty" . $c{$n}{$m} if $ten == 4;
			    $c{$n}{$m} = "\\Fifty" . $c{$n}{$m} if $ten == 5;
			    $c{$n}{$m} = "\\Sixty" . $c{$n}{$m} if $ten == 6;
			    $c{$n}{$m} = "\\Seventy" . $c{$n}{$m} if $ten == 7;
			    $c{$n}{$m} = "\\Eighty" . $c{$n}{$m} if $ten == 8;
			    $c{$n}{$m} = "\\Ninety" . $c{$n}{$m} if $ten == 9;
			}
		    }
		}
		#$c{$n}{$m} = "\\shoveright " . $c{$n}{$m};
	    }
	}
    }
}


sub onenum2rods {
    my ($number) = @_;
    # unless ($noninteger) {}
    my $cresult = "";
    if ($number >= 0 ) {
	while ( $number ne "" ) { 
	    my $digit = "";
	    $number =~s/\d$//;
	    $digit = $&;
	    $cresult = "~" . $cresult;
	    $cresult = "\\zero" . $cresult if $digit == 0;
	    $cresult = "\\one" . $cresult if $digit == 1;
	    $cresult = "\\two" . $cresult if $digit == 2;
	    $cresult = "\\three" . $cresult if $digit == 3;
	    $cresult = "\\four" . $cresult if $digit == 4;
	    $cresult = "\\five" . $cresult if $digit == 5;
	    $cresult = "\\six" . $cresult if $digit == 6;
	    $cresult = "\\seven" . $cresult if $digit == 7;
	    $cresult = "\\eight" . $cresult if $digit == 8;
	    $cresult = "\\nine" . $cresult if $digit == 9;
	    if ($number ne "") {
		my $ten = "";
		$number =~s/\d$//;
		$ten = $&;
		$cresult = "~" . $cresult;
		$cresult = "\\zero" . $cresult if $ten == 0;
		$cresult = "\\ten" . $cresult if $ten == 1;
		$cresult = "\\twenty" . $cresult if $ten == 2;
		$cresult = "\\thirty" . $cresult if $ten == 3;
		$cresult = "\\forty" . $cresult if $ten == 4;
		$cresult = "\\fifty" . $cresult if $ten == 5;
		$cresult = "\\sixty" . $cresult if $ten == 6;
		$cresult = "\\seventy" . $cresult if $ten == 7;
		$cresult = "\\eighty" . $cresult if $ten == 8;
		$cresult = "\\ninety" . $cresult if $ten == 9;
	    }
	}
    }else{
	$number = -$number;
	while ( $number ne "" ) { 
	    my $digit = "";
	    $number =~s/\d$//;
	    $digit = $&;
	    $cresult = "~" . $cresult;
	    $cresult = "\\Zero" . $cresult if $digit == 0;
	    $cresult = "\\One" . $cresult if $digit == 1;
	    $cresult = "\\Two" . $cresult if $digit == 2;
	    $cresult = "\\Three" . $cresult if $digit == 3;
	    $cresult = "\\Four" . $cresult if $digit == 4;
	    $cresult = "\\Five" . $cresult if $digit == 5;
	    $cresult = "\\Six" . $cresult if $digit == 6;
	    $cresult = "\\Seven" . $cresult if $digit == 7;
	    $cresult = "\\Eight" . $cresult if $digit == 8;
	    $cresult = "\\Nine" . $cresult if $digit == 9;
	    if ($number ne "") {
		my $ten = "";
		$number =~s/\d$//;
		$ten = $&;
		$cresult = "~" . $cresult;
		$cresult = "\\Zero" . $cresult if $ten == 0;
		$cresult = "\\Ten" . $cresult if $ten == 1;
		$cresult = "\\Twenty" . $cresult if $ten == 2;
		$cresult = "\\Thirty" . $cresult if $ten == 3;
		$cresult = "\\Forty" . $cresult if $ten == 4;
		$cresult = "\\Fifty" . $cresult if $ten == 5;
		$cresult = "\\Sixty" . $cresult if $ten == 6;
		$cresult = "\\Seventy" . $cresult if $ten == 7;
		$cresult = "\\Eighty" . $cresult if $ten == 8;
		$cresult = "\\Ninety" . $cresult if $ten == 9;
	    }
	}
    }
    #$cresult = "\\shoveright " . $cresult;
    return $cresult;
}

sub print_abstractmatrix {
    my ($t) = @_;
    $abstractmatrices[$t] = "";
    foreach my $n (1..$N) {
	foreach my $m (1..$N) {
	    if ($n == $N and $m == 1) {
		$abstractmatrices[$t] .= qq{ l_{$N} & };
	    }elsif ($n == $N and $m <= $t + 1) {
		if ($m % 2 == 0 ) {
		    $abstractmatrices[$t] .= qq{ - };
		};
		my $r = $m -1;
		$abstractmatrices[$t] .= qq{ l_{$N} };
		foreach my $i (1..$t -1) {
		    if ($i < $m -1 ) {
			$abstractmatrices[$t] .= qq{ l_{$i}  };
		    }
		}
		$abstractmatrices[$t] .= qq{ l_{$r} & };
	    }elsif ($m == $n) {
		$abstractmatrices[$t] .= qq{ k_{$n} & };
	    }elsif ($m == $n+1) {
		$abstractmatrices[$t] .= qq{ l_{$n} & };
	    }else{
		$abstractmatrices[$t] .= qq{ 0 & };
	    }; 
	};
	$abstractmatrices[$t] .= qq{ b_{$n} \\\\  };
    };
    return $abstractmatrices[$t];
}

sub print_a {
    $print_a = qq{<table>};
    my $format = "";
    my $i = 0;
    foreach my $n (1..$N) {
	$print_a .= qq{<tr>};
	foreach my $m (1..$N) {
	    if (($m == $n+1) or ($m == $n) or ($m == 1 and $n == $N)) {
		$print_a .= qq{<td><input type="text" name="b[$n][$m]" default value="$b{$n}{$m}" align="center" size="7" maxlength="7" border="0"></td>};
	    }else{
		$print_a .= qq{<td>0</td>};
	    }
	};
	$print_a .= qq{<td><input type="text" name="b[$n][$M]" default value="$b{$n}{$M}" size="10" maxlength="10" border="0" align="center"></td>};
	$print_a .= qq{</tr>};
    };
    $print_a .= qq{</table>};
    return $print_a;
};

sub print_matrix {
    $matrix = "";
    foreach my $n (1..$N) {
	foreach my $m (1..$N) {
	    $matrix .= qq{ $a{$n}{$m} & };
	};
	$matrix .= qq{ $a{$n}{$M} \\\\ };
    };
    return $matrix;
}

sub print_cmatrix {
    $cmatrix = "";
    unless ($noninteger){
	foreach my $m (1..$M) {
	    foreach my $n (reverse (2..$N)) {
		$cmatrix .= qq{ $c{$n}{$m} ~ \\vline ~ & };
	    };
	    $cmatrix .= qq{ $c{1}{$m} \\\\  };
	    unless ($m == $M) {$cmatrix .= qq{  \\hline   }};
	};
    };
    return $cmatrix;
};

#PRINT HTML SUBROUTINES

sub print_header {# style = "font-size: 12px; font-family: 'Impact'; background-color : yellow;  font-weight : bold;  font-size: 12px; font-family: 'Helvetica'; text-decoration : underline"
		      my $print_header = qq{ 
			  <style type="text/css">
			      p {font-family: serif; font-weight: lighter;}
			  h3 {font-family: Arial Arial Black; font-weight: bolder; }
			  th {font-family: Arial Arial Black; font-size: small; text-align: center; vertical-align: bottom; border-collapse: collapse; border-spacing: 0px 0px;}
			  td {font-family: Arial Arial Black; text-align: center; vertical-align: center; border-collapse: collapse; border-spacing: 0px 0px; width: 5em}
			  table {border-collapse: separate; border-spacing: 0px 1px; border: 1px solid black; table-layout: fixed; font-color: blue; } 
			  </style> }; # background-color: #bbf
		      # $print_header .= qq{<tr><th colspan = "1"></th>};
		      # foreach my $m (@m) {
		      # $print_header .= qq{<th colspan = "1">$m</th>};
		      # };
		      #$print_header .= qq{</tr>};
		  };

#PRINT LATEX OUTPUT
# {\setlength{\arrayrulewidth}{0.05pt} %default is 0.4pt
#   \setlength{\arraycolsep}{2pt}%default is 5pt
#  \renewcommand{\arraystretch}{1.2}%default is 1

sub createout1 {
    foreach my $i (0..$N-2){
	$output .= qq{
	    <p></p>
		<h4>Step $i<\h4>
		    <p>$boardnotes[$i]</p>
			<p><img src="../cgi-bin/mathtex.cgi?
\\renewcommand{\\arraystretch}{2}
\\setlength{\\arrayrulewidth}{0.05pt}
\\fbox{
\\begin{equation*}
\\begin{array}{*{$N}r}
$cmatrices[$i]
\\end{array} 
\\end{equation*}
}
" alt="" border=0 align=middle>
    $calcnotes[$i] 
	<p>
	    <img src="../cgi-bin/mathtex.cgi?
\\usepackage{euler}
\\begin{equation*}
\\begin{bmatrix}
$matrices[$i]
\\end{bmatrix}
\\end{equation*}
" alt="" border=0 align=middle>
    <p>
	$formulanotes[$i] 
	    <img src="../cgi-bin/mathtex.cgi?
\\usepackage{euler}
\\begin{equation*}
\\begin{bmatrix}
$abstractmatrices[$i]
\\end{bmatrix}
\\end{equation*}
" alt="" border=0 align=middle>
    <p>
    };
    }
    return $output;
}

sub createout2 {
    foreach my $i ($N..2*$N-2){
	$output .= qq{
	    <p>
		<h4>Step $i<\h4>
		    <p>
			<img src="../cgi-bin/mathtex.cgi?
\\usepackage{scalefnt}
\\scalefont{1}
\\fbox{
\\begin{equation*}
\\begin{array}{*{$N}r}
$cresult[$i+1-$N]
\\end{array} 
\\end{equation*}
}
" alt="" border=0 align=middle>
    <p>
	<img src="../cgi-bin/mathtex.cgi?
\\usepackage{euler}
\\begin{equation*}
$result[$i+1-$N]
\\end{equation*}
" alt="" border=0 align=middle>
    <p>
	<img src="../cgi-bin/mathtex.cgi?
\\usepackage{euler}
\\begin{equation*}
$formula[$i]
\\end{equation*}
" alt="" border=0 align=middle>
    <p>
    };
    }
    return $output;
}

sub createout3 {
    my $laststep = 2*$N-1;
    $output .= qq{
	<p>
	    <h4>Step $laststep<\h4>
		<p>
		    <img src="../cgi-bin/mathtex.cgi?
\\usepackage{euler}
\\begin{equation*}
$result[$N]
\\end{equation*}
" alt="" border=0 align=middle>
     <p>
	 <img src="../cgi-bin/mathtex.cgi?
\\usepackage{euler}
\\begin{equation*}
$formula[2*$N]
\\end{equation*}
" alt="" border=0 align=middle>
    <p>
    };
    return $output;
}

#CGI SUBROUTINES

sub choose_options {
    if ($query->param('JZSSnum') && ($query->param('JZSSnum') != $JZSSnum)) {
	$JZSSnum = $query->param('JZSSnum');
	&JZSS($JZSSnum);
    }elsif (0==1){ # ($query->param('N') && ($query->param('N') != $N)) {
	$N = $query->param('N');
	unless (($N >= 1) and ($N <= 5)) {$N = 3};
	$M = $N + 1;
	&random_a;
    }else{
	$JZSSnum = $query->param('OldJZSSnum'); #= $query->param("N");
	$N = $query->param('N'); #= $query->param("N");
	$error .= " <p>My old N is $N </p>";
	$M = $N+1;
	foreach my $n (1..$N) {
	    foreach my $m (1..$M) {
		if (($m == $n+1) or ($m == $n) or ($m == 1 and $n == $N) or $m == $M) {
		    my $input = $query->param("b[$n][$m]");
		    $input =~ s/\s+//g;
		    if ($input =~ m/^\-?\d+(\/\d+)?$/) {
			$b{$n}{$m} = $input;
		    }else{
			$inputerror .= qq{<p>"$input" is not valid input. Entries must be an integer or a proper fraction. };
			if ($input =~ m/\-?\d+(\/\d+)?/) {
			    $b{$n}{$m} = $&;
			}else{
			    $b{$n}{$m} = 0;
			}
			$inputerror .= qq{The entry has been set to $b{$n}{$m}.</p>};
		    }
		}else{
		    $b{$n}{$m} = 0;
		}
		$JZSS[$JZSSnum][$n-1][$m-1] = "$b{$n}{$m}";
	    }
	}
	&JZSS($JZSSnum);
    }
    if ($query->param('usegcf')) {
	$usegcf = $query->param('usegcf');
	unless ($usegcf == 1) {$usegcf = 0};
    }
}

#PRINT HTML PAGE

print $query->header, 
    $query->start_html('Chinese linear algebra'), 
    h2('Determinants'),
    p,
    start_form,
		hr,
    "Problem:",  popup_menu(-name=>'JZSSnum', -values=>\@JZSSproblems, -default=>""),p,
    submit(-name=>'Choose new problem'),
    p,
    end_form;
$query->end_html; 


#PROCESS SUBROUTINES
if ($query->param()) {
    &choose_options;
    $table_a = &print_a; 
    $table_header = &print_header; 
    #&rowReduction;
    #&backSubstitution;
    #&divideANN;
    &determinants;
    &createout1;
    &createout2;
    &createout3;
    
    print 
	start_form,
	hr,
	hidden(-name=>'N', -default=>["$N"]),
	hidden(-name=>'OldJZSSnum', -default=>["$JZSSnum"]),
	p, $table_header, $table_a, p,
	submit(-name=>'Recalculate with new values'), p,
	"$inputerror",
	p,
	# reset(-name=>'Reset to original values'), p,
	hr,
	end_form;
    print qq{$output};
    
    $query->end_html; 
    #$query->delete_all();
}


# my @names = $query->param;
# $error .="@names ";
# 
# my $params = $query->Vars;
# print $params->{'address'};
# my @foo = split("\0",$params->{'foo'});
# my %params = $query->Vars;
# use CGI ':cgi-lib';
# $params = Vars;
# $error .="$params";
# foreach my $key (%params) {
# $error .= "<p>$key => $params{$key}</p>";
# }
# print qq{$error};


